Objectives and Output

For more on how to manipulate tidy texts and dataframes: R for Data Science, chapter 5: http://r4ds.had.co.nz/ (Links to an external site.)

For an introduction to R programming: The Art of R Programming, chapters 1 and 2: https://ebookcentral.proquest.com/lib/fsu/detail.action?docID=1137514

R for Data Science

Chapter 5: Data Transformation

5.1 Introduction

how to transform your data using the dplyr package (and a new dataset on flights)

5.1.1 Prerequisites

At this point, I was having trouble installing the tidyverse package. so I had to update my R version

To do so, I went http://mercury.webster.edu/aleshunas/R_learning_infrastructure/Updating%20R%20and%20RStudio.html for update instructions.

R version 3.2.3 (2015-12-10) – “Wooden Christmas-Tree” ^ This is my current version. As you can see, it was released around 2015. The current version available is R version 3.5.1 (Feather Spray) released 2018-07-02.

So even thoughI tried to install a new R package, it seems that the packages dpylr and tidytext provide the same function.

library(nycflights13)
library(tidyverse)
── Attaching packages ─────────────────── tidyverse 1.2.1 ──
✔ ggplot2 3.0.0     ✔ purrr   0.2.5
✔ tibble  1.4.2     ✔ dplyr   0.7.6
✔ tidyr   0.8.1     ✔ stringr 1.3.1
✔ readr   1.1.1     ✔ forcats 0.3.0
── Conflicts ────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
library(tidytext)
library(dplyr)

(Conflicting function calls) If you want to use the base version of these functions after loading dplyr, you’ll need to use their full names: stats::filter() and stats::lag().

5.1.2 nycflights13
flights
5.1.3 dplyr basics

filter() arrange() select() mutate() summarize()

group_by()

5.2 filter rows with filter()

filter(flights, month == 1, day == 1)
jan1 <- filter(flights, month == 1, day == 1)
(dec25 <- filter(flights, month == 12, day == 25))
5.2.1 Comparisons
sqrt(2) ^ 2 == 2
[1] FALSE
1 / 49 * 49 == 1
[1] FALSE
near(sqrt(2) ^ 2,  2)
[1] TRUE
near(1 / 49 * 49, 1)
[1] TRUE
5.2.2 Logical Operators
filter(flights, month == 11 | month == 12)
nov_dec <- filter(flights, month %in% c(11, 12))
filter(flights, !(arr_delay > 120 | dep_delay > 120))
filter(flights, arr_delay <= 120, dep_delay <= 120)
5.2.3 Missing Values
NA > 5
[1] NA
10 == NA
[1] NA
NA + 10
[1] NA
NA / 2
[1] NA
NA == NA
[1] NA
# Let x be Mary's age. We don't know how old she is.
x <- NA
# Let y be John's age. We don't know how old he is.
y <- NA
# Are John and Mary the same age?
x == y
[1] NA
is.na(x)
[1] TRUE
df <- tibble(x = c(1, NA, 3))
filter(df, x > 1)
filter(df, is.na(x) | x > 1)
5.2.4 Exercises

Find all flights

# Had an arrival delay of two or more hours
arrDelay2 <- filter(flights, arr_delay >= 120)
# Flew to Houston (IAH or HOU)
filter(flights, dest == "IAH"| dest == "HOU")
# Were operated by United, American, or Delta
filter(flights, carrier %in% c("UA", "AA", "DL"))
# Departed in summer (July, August, and September)
filter(flights, month %in% c(7, 8, 9))
# Arrived more than two hours late, but didn’t leave late
filter(flights, arr_delay > 2 & dep_delay <= 0)
# Were delayed by at least an hour, but made up over 30 minutes in flight
filter(flights, dep_delay >= 60 & sched_arr_time - arr_time > 30)
# Departed between midnight and 6am (inclusive)
filter(flights, dep_time >= 0  & dep_time <= 600)

Another useful dplyr filtering helper is between(). What does it do? Can you use it to simplify the code needed to answer the previous challenges?

between() uses a upper and lower bound to note which of the list lies between these values

filter(flights, between(dep_time, 0, 600))

How many flights have a missing dep_time? What other variables are missing? What might these rows represent?

# flights with missing departure times 
# this is for flights that have been cancelled
nrow(filter(flights, is.na(dep_time)))
[1] 8255

Why is NA ^ 0 not missing? Why is NA | TRUE not missing? Why is FALSE & NA not missing? Can you figure out the general rule? (NA * 0 is a tricky counterexample!)

NA^0
[1] 1
NA | TRUE
[1] TRUE
FALSE & NA
[1] FALSE

5.3 Arrange rows with arrange()

arrange(flights, year, month, day)
arrange(flights, desc(dep_delay))
df <- tibble(x = c(5, 2, NA))
arrange(df, x)
arrange(df, desc(x))
5.3.1 Exercises
# how to use arrange() to sort all missing values to the start
arrange(flights, !is.na(dep_time), dep_time)
# i still don't really understand why this works. only that it does (somehow)
# oh got it now. 
# Sort flights to find the most delayed flights. 
arrange(flights, desc(dep_delay), desc(arr_delay))
# Find the flights that left earliest.
arrange(flights, dep_delay)
# Sort flights to find the fastest flights
arrange(flights, air_time)
# which flights travelled the longest
arrange(flights, desc(distance))
# which flights travelled the shortest
arrange(flights, distance)

5.4 Select columns with select()

# selecting specific columns
select(flights, year, month, day)
# select using : which means all columns in between
select(flights, year:day)
# select all columns except for those specified (-)
select(flights, -(year:day))

helper functions

starts_with(“abc”): matches names that begin with “abc”.

ends_with(“xyz”): matches names that end with “xyz”.

contains(“ijk”): matches names that contain “ijk”.

matches(“(.)\1”): selects variables that match a regular expression. This one matches any variables that contain repeated characters. You’ll learn more about regular expressions in strings.

num_range(“x”, 1:3): matches x1, x2 and x3.

select() has rename capabilities but its finicky at best, just use rename() instead

rename(flights, tail_num = tailnum)
5.4.1 Exercises
# select dep_time, dep_delay, arr_time, and arr_delay from flights.
# select(flights, dep_time, dep_delay, arr_time, arr_delay)
select(flights, dep_time:arr_delay, -sched_dep_time, -sched_arr_time)
# same variable multiple times
select(flights, year, year)
vars <- c("year", "month", "day", "dep_delay", "arr_delay")
select(flights, one_of(vars))
# what you think it does: if it contains TIME (case sensitive or at the beginning of the column name) it will keep that column

# what it actually does: if it contains time anywhere (case insensitive) in the column name it will keep that column
select(flights, contains("TIME"))
# to change how select deals with case sensitivity, try 
select(flights, starts_with("TIME"))

5.5 Add new variables with mutate()

mutate() always adds new columns at the end of your dataset see all the columns is View()

flights_sml <- select(flights, 
  year:day, 
  ends_with("delay"), 
  distance, 
  air_time
)
mutate(flights_sml,
  gain = dep_delay - arr_delay,
  speed = distance / air_time * 60
)
5.5.1 filter rows with filter()
5.5.1 filter rows with filter()

5.5 filter rows with filter()

5.5.1 filter rows with filter()
5.5.1 filter rows with filter()
5.5.1 filter rows with filter()
5.5.1 filter rows with filter()
5.5.1 filter rows with filter()
5.5.1 filter rows with filter()
5.5.1 filter rows with filter()

5.5 filter rows with filter()

5.5.1 filter rows with filter()

Text Mining with R

Ch 2: Sentient Analysis with tidy Data

2.1 The sentiments dataset

sentiments

Ch 3: Analyzing word and document frequency: tf-idf

Examples from this chapter were already done in the previous homework assignment

LS0tCnRpdGxlOiAiV2VlayAzOiBFeHBlcmltZW50cyAtIEVsYWJvcmF0aW9ucyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMgT2JqZWN0aXZlcyBhbmQgT3V0cHV0CgpGb3IgbW9yZSBvbiBob3cgdG8gbWFuaXB1bGF0ZSB0aWR5IHRleHRzIGFuZCBkYXRhZnJhbWVzOiBSIGZvciBEYXRhIFNjaWVuY2UsIGNoYXB0ZXIgNTogaHR0cDovL3I0ZHMuaGFkLmNvLm56LyAoTGlua3MgdG8gYW4gZXh0ZXJuYWwgc2l0ZS4pCgpGb3IgYW4gaW50cm9kdWN0aW9uIHRvIFIgcHJvZ3JhbW1pbmc6IFRoZSBBcnQgb2YgUiBQcm9ncmFtbWluZywgY2hhcHRlcnMgMSBhbmQgMjogaHR0cHM6Ly9lYm9va2NlbnRyYWwucHJvcXVlc3QuY29tL2xpYi9mc3UvZGV0YWlsLmFjdGlvbj9kb2NJRD0xMTM3NTE0CgoKIyMgUiBmb3IgRGF0YSBTY2llbmNlCgojIyMgQ2hhcHRlciA1OiBEYXRhIFRyYW5zZm9ybWF0aW9uCgojIyMjIDUuMSBJbnRyb2R1Y3Rpb24KCmhvdyB0byB0cmFuc2Zvcm0geW91ciBkYXRhIHVzaW5nIHRoZSBkcGx5ciBwYWNrYWdlIChhbmQgYSBuZXcgZGF0YXNldCBvbiBmbGlnaHRzKQoKIyMjIyMgNS4xLjEgUHJlcmVxdWlzaXRlcwpBdCB0aGlzIHBvaW50LCBJIHdhcyBoYXZpbmcgdHJvdWJsZSBpbnN0YWxsaW5nIHRoZSB0aWR5dmVyc2UgcGFja2FnZS4gc28gSSBoYWQgdG8gdXBkYXRlIG15IFIgdmVyc2lvbiAKClRvIGRvIHNvLCBJIHdlbnQgaHR0cDovL21lcmN1cnkud2Vic3Rlci5lZHUvYWxlc2h1bmFzL1JfbGVhcm5pbmdfaW5mcmFzdHJ1Y3R1cmUvVXBkYXRpbmclMjBSJTIwYW5kJTIwUlN0dWRpby5odG1sIGZvciB1cGRhdGUgaW5zdHJ1Y3Rpb25zLiAKCipSIHZlcnNpb24gMy4yLjMgKDIwMTUtMTItMTApIC0tICJXb29kZW4gQ2hyaXN0bWFzLVRyZWUiKgpeIFRoaXMgaXMgbXkgY3VycmVudCB2ZXJzaW9uLiBBcyB5b3UgY2FuIHNlZSwgaXQgd2FzIHJlbGVhc2VkIGFyb3VuZCAyMDE1LiBUaGUgY3VycmVudCB2ZXJzaW9uIGF2YWlsYWJsZSBpcyBSIHZlcnNpb24gMy41LjEgKEZlYXRoZXIgU3ByYXkpIHJlbGVhc2VkIDIwMTgtMDctMDIuCgpTbyBldmVuIHRob3VnaEkgdHJpZWQgdG8gaW5zdGFsbCBhIG5ldyBSIHBhY2thZ2UsIGl0IHNlZW1zIHRoYXQgdGhlIHBhY2thZ2VzIGRweWxyIGFuZCB0aWR5dGV4dCBwcm92aWRlIHRoZSBzYW1lIGZ1bmN0aW9uLgpgYGB7cn0KbGlicmFyeShueWNmbGlnaHRzMTMpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHRpZHl0ZXh0KQpsaWJyYXJ5KGRwbHlyKQpgYGAKCihDb25mbGljdGluZyBmdW5jdGlvbiBjYWxscykKSWYgeW91IHdhbnQgdG8gdXNlIHRoZSBiYXNlIHZlcnNpb24gb2YgdGhlc2UgZnVuY3Rpb25zIGFmdGVyIGxvYWRpbmcgZHBseXIsIHlvdeKAmWxsIG5lZWQgdG8gdXNlIHRoZWlyIGZ1bGwgbmFtZXM6IHN0YXRzOjpmaWx0ZXIoKSBhbmQgc3RhdHM6OmxhZygpLgoKIyMjIyMgNS4xLjIgbnljZmxpZ2h0czEzCgpgYGB7cn0KZmxpZ2h0cwpgYGAKCiMjIyMjIDUuMS4zIGRwbHlyIGJhc2ljcwoKZmlsdGVyKCkKYXJyYW5nZSgpCnNlbGVjdCgpCm11dGF0ZSgpCnN1bW1hcml6ZSgpCgpncm91cF9ieSgpCgojIyMjIDUuMiBmaWx0ZXIgcm93cyB3aXRoIGZpbHRlcigpCgpgYGB7cn0KZmlsdGVyKGZsaWdodHMsIG1vbnRoID09IDEsIGRheSA9PSAxKQpgYGAKCgpgYGB7cn0KamFuMSA8LSBmaWx0ZXIoZmxpZ2h0cywgbW9udGggPT0gMSwgZGF5ID09IDEpCmBgYAoKCmBgYHtyfQooZGVjMjUgPC0gZmlsdGVyKGZsaWdodHMsIG1vbnRoID09IDEyLCBkYXkgPT0gMjUpKQpgYGAKCiMjIyMjIDUuMi4xIENvbXBhcmlzb25zCmBgYHtyfQpzcXJ0KDIpIF4gMiA9PSAyCjEgLyA0OSAqIDQ5ID09IDEKYGBgCgoKYGBge3J9Cm5lYXIoc3FydCgyKSBeIDIsICAyKQpuZWFyKDEgLyA0OSAqIDQ5LCAxKQpgYGAKCiMjIyMjIDUuMi4yIExvZ2ljYWwgT3BlcmF0b3JzCmBgYHtyfQpmaWx0ZXIoZmxpZ2h0cywgbW9udGggPT0gMTEgfCBtb250aCA9PSAxMikKYGBgCgpgYGB7cn0Kbm92X2RlYyA8LSBmaWx0ZXIoZmxpZ2h0cywgbW9udGggJWluJSBjKDExLCAxMikpCmBgYAoKYGBge3J9CmZpbHRlcihmbGlnaHRzLCAhKGFycl9kZWxheSA+IDEyMCB8IGRlcF9kZWxheSA+IDEyMCkpCmZpbHRlcihmbGlnaHRzLCBhcnJfZGVsYXkgPD0gMTIwLCBkZXBfZGVsYXkgPD0gMTIwKQpgYGAKCiMjIyMjIDUuMi4zIE1pc3NpbmcgVmFsdWVzCgpgYGB7cn0KTkEgPiA1CjEwID09IE5BCk5BICsgMTAKTkEgLyAyCmBgYAoKYGBge3J9Ck5BID09IE5BCmBgYAoKYGBge3J9CiMgTGV0IHggYmUgTWFyeSdzIGFnZS4gV2UgZG9uJ3Qga25vdyBob3cgb2xkIHNoZSBpcy4KeCA8LSBOQQoKIyBMZXQgeSBiZSBKb2huJ3MgYWdlLiBXZSBkb24ndCBrbm93IGhvdyBvbGQgaGUgaXMuCnkgPC0gTkEKCiMgQXJlIEpvaG4gYW5kIE1hcnkgdGhlIHNhbWUgYWdlPwp4ID09IHkKYGBgCgpgYGB7cn0KaXMubmEoeCkKYGBgCgpgYGB7cn0KZGYgPC0gdGliYmxlKHggPSBjKDEsIE5BLCAzKSkKZmlsdGVyKGRmLCB4ID4gMSkKCmZpbHRlcihkZiwgaXMubmEoeCkgfCB4ID4gMSkKYGBgCgojIyMjIyA1LjIuNCBFeGVyY2lzZXMKRmluZCBhbGwgZmxpZ2h0cwpgYGB7cn0KIyBIYWQgYW4gYXJyaXZhbCBkZWxheSBvZiB0d28gb3IgbW9yZSBob3VycwphcnJEZWxheTIgPC0gZmlsdGVyKGZsaWdodHMsIGFycl9kZWxheSA+PSAxMjApCmBgYAoKYGBge3J9CiMgRmxldyB0byBIb3VzdG9uIChJQUggb3IgSE9VKQpmaWx0ZXIoZmxpZ2h0cywgZGVzdCA9PSAiSUFIInwgZGVzdCA9PSAiSE9VIikKYGBgCgpgYGB7cn0KIyBXZXJlIG9wZXJhdGVkIGJ5IFVuaXRlZCwgQW1lcmljYW4sIG9yIERlbHRhCmZpbHRlcihmbGlnaHRzLCBjYXJyaWVyICVpbiUgYygiVUEiLCAiQUEiLCAiREwiKSkKYGBgCgpgYGB7cn0KIyBEZXBhcnRlZCBpbiBzdW1tZXIgKEp1bHksIEF1Z3VzdCwgYW5kIFNlcHRlbWJlcikKZmlsdGVyKGZsaWdodHMsIG1vbnRoICVpbiUgYyg3LCA4LCA5KSkKYGBgCgpgYGB7cn0KIyBBcnJpdmVkIG1vcmUgdGhhbiB0d28gaG91cnMgbGF0ZSwgYnV0IGRpZG7igJl0IGxlYXZlIGxhdGUKZmlsdGVyKGZsaWdodHMsIGFycl9kZWxheSA+IDEyMCAmIGRlcF9kZWxheSA8PSAwKQpgYGAKCmBgYHtyfQojIFdlcmUgZGVsYXllZCBieSBhdCBsZWFzdCBhbiBob3VyLCBidXQgbWFkZSB1cCBvdmVyIDMwIG1pbnV0ZXMgaW4gZmxpZ2h0CmZpbHRlcihmbGlnaHRzLCBkZXBfZGVsYXkgPj0gNjAgJiBzY2hlZF9hcnJfdGltZSAtIGFycl90aW1lID4gMzApCmBgYAoKCmBgYHtyfQojIERlcGFydGVkIGJldHdlZW4gbWlkbmlnaHQgYW5kIDZhbSAoaW5jbHVzaXZlKQpmaWx0ZXIoZmxpZ2h0cywgZGVwX3RpbWUgPj0gMCAgJiBkZXBfdGltZSA8PSA2MDApCmBgYAoKQW5vdGhlciB1c2VmdWwgZHBseXIgZmlsdGVyaW5nIGhlbHBlciBpcyBiZXR3ZWVuKCkuIFdoYXQgZG9lcyBpdCBkbz8gQ2FuIHlvdSB1c2UgaXQgdG8gc2ltcGxpZnkgdGhlIGNvZGUgbmVlZGVkIHRvIGFuc3dlciB0aGUgcHJldmlvdXMgY2hhbGxlbmdlcz8KCiAgYmV0d2VlbigpIHVzZXMgYSB1cHBlciBhbmQgbG93ZXIgYm91bmQgdG8gbm90ZSB3aGljaCBvZiB0aGUgbGlzdCBsaWVzIGJldHdlZW4gdGhlc2UgdmFsdWVzCiAgCmBgYHtyfQojIERlcGFydGVkIGJldHdlZW4gbWlkbmlnaHQgYW5kIDZhbSAoaW5jbHVzaXZlKSAKIyB1c2luZyBiZXR3ZWVuIGZ1bmN0aW9uCmZpbHRlcihmbGlnaHRzLCBiZXR3ZWVuKGRlcF90aW1lLCAwLCA2MDApKQpgYGAKCgpIb3cgbWFueSBmbGlnaHRzIGhhdmUgYSBtaXNzaW5nIGRlcF90aW1lPyBXaGF0IG90aGVyIHZhcmlhYmxlcyBhcmUgbWlzc2luZz8gV2hhdCBtaWdodCB0aGVzZSByb3dzIHJlcHJlc2VudD8KYGBge3J9CiMgbnVtYmVyIG9mIGZsaWdodHMgd2l0aCBtaXNzaW5nIGRlcGFydHVyZSB0aW1lcyAKIyB0aGlzIGlzIGZvciBmbGlnaHRzIHRoYXQgaGF2ZSBiZWVuIGNhbmNlbGxlZApucm93KGZpbHRlcihmbGlnaHRzLCBpcy5uYShkZXBfdGltZSkpKQpgYGAKCldoeSBpcyBOQSBeIDAgbm90IG1pc3Npbmc/IFdoeSBpcyBOQSB8IFRSVUUgbm90IG1pc3Npbmc/IFdoeSBpcyBGQUxTRSAmIE5BIG5vdCBtaXNzaW5nPyBDYW4geW91IGZpZ3VyZSBvdXQgdGhlIGdlbmVyYWwgcnVsZT8gKE5BICogMCBpcyBhIHRyaWNreSBjb3VudGVyZXhhbXBsZSEpCgpgYGB7cn0KIyByZXN1bHRzIGluIDEKIyBhbnl0aGluZyB0byB0aGUgcG93ZXIgb2YgMCB3aWxsIGFsd2F5cyBiZSAxCk5BXjAKYGBgCmBgYHtyfQojIHJlc3VsdHMgaW4gVFJVRQojIGFueXRoaW5nIHdpdGggVFJVRSBpbiBhbiBvciBzdGF0ZW1lbnQgd2lsbCBhbHdheXMgYmUgdHJ1ZQpOQSB8IFRSVUUKYGBgCmBgYHtyfQojIFNpbmNlIHRoZSB0d28gcG9zc2liaWxpdGllcyB3aWxsIGVpdGhlciBiZSB0cnVlIG9yIGZhbHNlIGFuZCBpZiB0aGVyZSBpcyBvbmUgZmFsc2UgaW4gYW4gQU5EIHN0YXRlbWVudCwgaXQgd2lsbCBhbHdheXMgYmUgZmFsc2UKRkFMU0UgJiBOQQpgYGAKCiMjIyMgNS4zIEFycmFuZ2Ugcm93cyB3aXRoIGFycmFuZ2UoKQoKYGBge3J9CiMgQXNjZW5kaW5nIGluIHllYXIgdGhlbiBtb250aCBhbmQgdGhlbiBkYXkKYXJyYW5nZShmbGlnaHRzLCB5ZWFyLCBtb250aCwgZGF5KQpgYGAKCmBgYHtyfQojIGRlc2MoeCkgaXMgdGhlIHggY29sdW1uIGluIGRlc2NlbmRpbmcgb3JkZXIgCmFycmFuZ2UoZmxpZ2h0cywgZGVzYyhkZXBfZGVsYXkpKQpgYGAKCmBgYHtyfQojIFB1cnBvc2U6IG1pc3NpbmcgdmFsdWVzIChOQSkgYXJlIGFsd2F5cyBzb3J0ZWQgYXQgdGhlIGVuZCAKZGYgPC0gdGliYmxlKHggPSBjKDUsIDIsIE5BKSkKYXJyYW5nZShkZiwgeCkKIyAyLCA1LCBOQQphcnJhbmdlKGRmLCBkZXNjKHgpKQojIDUsIDIsIE5BCmBgYAoKCiMjIyMjIDUuMy4xIEV4ZXJjaXNlcwoKYGBge3J9CiMgaG93IHRvIHVzZSBhcnJhbmdlKCkgdG8gc29ydCBhbGwgbWlzc2luZyB2YWx1ZXMgdG8gdGhlIHN0YXJ0CmFycmFuZ2UoZmxpZ2h0cywgIWlzLm5hKGRlcF90aW1lKSwgZGVwX3RpbWUpCgojIGkgc3RpbGwgZG9uJ3QgcmVhbGx5IHVuZGVyc3RhbmQgd2h5IHRoaXMgd29ya3MuIG9ubHkgdGhhdCBpdCBkb2VzIChzb21laG93KQojIG9oIGdvdCBpdCBub3cuIHNlY29uZCBwYXJhbWV0ZXIgc3RhdGVzIGlzIG5vdCBOQSBpbiBEZXBhcnR1cmUgdGltZSAod2hpY2ggd2lsbCBzb3J0IHRydWUgb3IgZmFsc2UgLS0gYW5kIGZhbHNlIGlzIGFscGhhYmV0aWNhbGx5IGJlZm9yZSB0cnVlKSB0aGVuIHNvcnRzIHRoZSBudW1iZXJzIGluIGFzY2VuZGluZyBvcmRlciAoYmVjYXVzZSB0aGUgZW50cmllcyB3aXRoIG51bWJlcnMgYXJlIGFsbCBlcXVhbGx5IHRydWUgW2lzIG5vdCBOQV0gKQpgYGAKCmBgYHtyfQojIFNvcnQgZmxpZ2h0cyB0byBmaW5kIHRoZSBtb3N0IGRlbGF5ZWQgZmxpZ2h0cy4gCiMgTm90IHN1cmUgd2hldGhlciB0aGlzIG1lYW5zIGRlcGFydHVyZSBvciBhcnJpdmFsIHNvIEkgaW5jbHVkZWQgYm90aAojIGRlc2MgYmVjYXVzZSB0aGUgbGFyZ2VyIHRoZSB2YWx1ZSwgdGhlIGJpZ2dlciB0aGUgZGVsYXkKYXJyYW5nZShmbGlnaHRzLCBkZXNjKGRlcF9kZWxheSksIGRlc2MoYXJyX2RlbGF5KSkKYGBgCgpgYGB7cn0KIyBGaW5kIHRoZSBmbGlnaHRzIHRoYXQgbGVmdCBlYXJsaWVzdC4KIyBlYXJseSA9IG5lZ2F0aXZlIGRlcGFydHVyZSBkZWxheSB0aW1lIChzb3J0IGFzY2VuZGluZykKYXJyYW5nZShmbGlnaHRzLCBkZXBfZGVsYXkpCmBgYAoKYGBge3J9CiMgU29ydCBmbGlnaHRzIHRvIGZpbmQgdGhlIGZhc3Rlc3QgZmxpZ2h0cwojIGJ5IG5vdCBvdmVyY29tcGxpY2F0aW5nIHRoaW5ncywgZmFzdGVzdCBJIGFzc3VtZSB0byBtZWFuIHNob3J0ZXN0IGFpciB0aW1lIChhc2NlbmRpbmcgb3JkZXIpCmFycmFuZ2UoZmxpZ2h0cywgYWlyX3RpbWUpCmBgYAoKYGBge3J9CiMgd2hpY2ggZmxpZ2h0cyB0cmF2ZWxsZWQgdGhlIGxvbmdlc3QKIyBzaW5jZSB3ZSd2ZSBhbHJlYWR5IGNvdmVyZWQgdGltZSwgdGhpcyBJIGFzc3VtZSB0byBtZWFuIGRpc3RhbmNlICh3aGljaCBpcyBhIGNvbHVtbikgYW5kIHRoZSBsb25nZXIgdGhlIGRpc3RhbmNlLCB0aGUgbG9uZ2VyIHRoZSB0cmF2ZWwgKGRlc2NlbmRpbmcgb3JkZXIpCmFycmFuZ2UoZmxpZ2h0cywgZGVzYyhkaXN0YW5jZSkpCmBgYAoKYGBge3J9CiMgd2hpY2ggZmxpZ2h0cyB0cmF2ZWxsZWQgdGhlIHNob3J0ZXN0CiMgYW5kIHRoZSBvcHBvc2l0ZSBmcm9tIHRoZSBwcmV2aW91cyBjaHVuaywgYXNjZW5kaW5nIG9yZGVyIGZvciBkaXN0YW5jZSBvZiB0aGUgc2hvcnRlc3QgZmxpZ2h0CmFycmFuZ2UoZmxpZ2h0cywgZGlzdGFuY2UpCmBgYAoKCiMjIyMgNS40IFNlbGVjdCBjb2x1bW5zIHdpdGggc2VsZWN0KCkKCmBgYHtyfQojIHNlbGVjdGluZyBzcGVjaWZpYyBjb2x1bW5zCnNlbGVjdChmbGlnaHRzLCB5ZWFyLCBtb250aCwgZGF5KQpgYGAKCmBgYHtyfQojIHNlbGVjdCB1c2luZyA6IHdoaWNoIG1lYW5zIGFsbCBjb2x1bW5zIGluIGJldHdlZW4Kc2VsZWN0KGZsaWdodHMsIHllYXI6ZGF5KQpgYGAKCmBgYHtyfQojIHNlbGVjdCBhbGwgY29sdW1ucyBleGNlcHQgZm9yIHRob3NlIHNwZWNpZmllZCAoLSkKc2VsZWN0KGZsaWdodHMsIC0oeWVhcjpkYXkpKQpgYGAKCmhlbHBlciBmdW5jdGlvbnMKCnN0YXJ0c193aXRoKCJhYmMiKTogbWF0Y2hlcyBuYW1lcyB0aGF0IGJlZ2luIHdpdGgg4oCcYWJj4oCdLgoKZW5kc193aXRoKCJ4eXoiKTogbWF0Y2hlcyBuYW1lcyB0aGF0IGVuZCB3aXRoIOKAnHh5euKAnS4KCmNvbnRhaW5zKCJpamsiKTogbWF0Y2hlcyBuYW1lcyB0aGF0IGNvbnRhaW4g4oCcaWpr4oCdLgoKbWF0Y2hlcygiKC4pXFwxIik6IHNlbGVjdHMgdmFyaWFibGVzIHRoYXQgbWF0Y2ggYSByZWd1bGFyIGV4cHJlc3Npb24uIFRoaXMgb25lIG1hdGNoZXMgYW55IHZhcmlhYmxlcyB0aGF0IGNvbnRhaW4gcmVwZWF0ZWQgY2hhcmFjdGVycy4gWW914oCZbGwgbGVhcm4gbW9yZSBhYm91dCByZWd1bGFyIGV4cHJlc3Npb25zIGluIHN0cmluZ3MuCgpudW1fcmFuZ2UoIngiLCAxOjMpOiBtYXRjaGVzIHgxLCB4MiBhbmQgeDMuCgpzZWxlY3QoKSBoYXMgcmVuYW1lIGNhcGFiaWxpdGllcyBidXQgaXRzIGZpbmlja3kgYXQgYmVzdCwganVzdCB1c2UgcmVuYW1lKCkgaW5zdGVhZAoKYGBge3J9CnJlbmFtZShmbGlnaHRzLCB0YWlsX251bSA9IHRhaWxudW0pCmBgYAoKCiMjIyMjIDUuNC4xIEV4ZXJjaXNlcwoKYGBge3J9CiMgc2VsZWN0IGRlcF90aW1lLCBkZXBfZGVsYXksIGFycl90aW1lLCBhbmQgYXJyX2RlbGF5IGZyb20gZmxpZ2h0cy4Kc2VsZWN0KGZsaWdodHMsIGRlcF90aW1lLCBkZXBfZGVsYXksIGFycl90aW1lLCBhcnJfZGVsYXkpCnNlbGVjdChmbGlnaHRzLCBkZXBfdGltZTphcnJfZGVsYXksIC1zY2hlZF9kZXBfdGltZSwgLXNjaGVkX2Fycl90aW1lKQoKYGBgCgpgYGB7cn0KIyBzYW1lIHZhcmlhYmxlIG11bHRpcGxlIHRpbWVzCnNlbGVjdChmbGlnaHRzLCB5ZWFyLCB5ZWFyKQojIHNob3dzIG9ubHkgb25lIGNvbHVtbgpgYGAKCmBgYHtyfQojIG9uZV9vZigpIGlzIGEgc2VsZWN0IGhlbHBlciBmdW5jdGlvbiBmb3Igc2VsZWN0KCkKIyBpdCB1c2VzIGEgY2hhcmFjdGVyIHZlY3RvciB0byBzZWxlY3QgdGhlIGNvbHVtbnMgc3BlY2lmaWVkIGluIHRoZSBjaGFyYWN0ZXIgdmVjdG9yCgojIHRoZXNlIGxpbmVzIHNwZWNpZnkgYSBjaGFyYWN0ZXIgdmVjdG9yICJ2YXJzIiBhbmQgc2VsZWN0KCkgd2lsbCBvdXRwdXQgYSB0YWJsZSBvZiB0aG9zZSB2YXJpYWJsZXMgbGlzdGVkIGluICJ2YXJzIgp2YXJzIDwtIGMoInllYXIiLCAibW9udGgiLCAiZGF5IiwgImRlcF9kZWxheSIsICJhcnJfZGVsYXkiKQpzZWxlY3QoZmxpZ2h0cywgb25lX29mKHZhcnMpKQpgYGAKCmBgYHtyfQojIHdoYXQgeW91IHRoaW5rIGl0IGRvZXM6IGlmIGl0IGNvbnRhaW5zIFRJTUUgKGNhc2Ugc2Vuc2l0aXZlIG9yIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGNvbHVtbiBuYW1lKSBpdCB3aWxsIGtlZXAgdGhhdCBjb2x1bW4KCiMgd2hhdCBpdCBhY3R1YWxseSBkb2VzOiBpZiBpdCBjb250YWlucyB0aW1lIGFueXdoZXJlIChjYXNlIGluc2Vuc2l0aXZlKSBpbiB0aGUgY29sdW1uIG5hbWUgaXQgd2lsbCBrZWVwIHRoYXQgY29sdW1uCnNlbGVjdChmbGlnaHRzLCBjb250YWlucygiVElNRSIpKQpgYGAKCmBgYHtyfQojIHRvIGNoYW5nZSBob3cgc2VsZWN0IGRlYWxzIHdpdGggdGhlIGNhc2UgZGVmYXVsdApzZWxlY3QoZmxpZ2h0cywgc3RhcnRzX3dpdGgoIlRJTUUiKSkKCiMgVGhpcyBsaW5lIHdpbGwgYmUgY2FzZSBzZW5zaXRpdmUgLSBidXQgaXQgcmVzdWx0cyBpbiBhbiBlcnJvciBiZWNhdXNlIHRoZXJlIGlzIG5vIFRJTUUgY29sdW1uCiMgc2VsZWN0KGZsaWdodHMsIG1hdGNoKCJUSU1FIikpCmBgYAoKIyMjIyA1LjUgQWRkIG5ldyB2YXJpYWJsZXMgd2l0aCBtdXRhdGUoKQoKbXV0YXRlKCkgYWx3YXlzIGFkZHMgbmV3IGNvbHVtbnMgYXQgdGhlIGVuZCBvZiB5b3VyIGRhdGFzZXQgCnNlZSBhbGwgdGhlIGNvbHVtbnMgaXMgVmlldygpCgpgYGB7cn0KIyBmbGlnaHRzX3NtbCBpcyBhIHN1YnNldCBvZiBmbGlnaHRzIHRoYXQgaGFzIHNvbWUgb2YgdGhlIHZhcmlhYmxlcyBmcm9tIGZsaWdodHMgKGZyb20geWVhciB0byBkYXkgLy8gaW5jbHVkaW5nIG1vbnRoLCBhbGwgY29sdW1ucyB0aGF0IGVuZCB3aXRoIGRlbGF5LCBkaXN0YW5jZSwgYW5kIGFpcnRpbWUpCmZsaWdodHNfc21sIDwtIHNlbGVjdChmbGlnaHRzLCAKICB5ZWFyOmRheSwgCiAgZW5kc193aXRoKCJkZWxheSIpLCAKICBkaXN0YW5jZSwgCiAgYWlyX3RpbWUKKQoKIyBhZGRzIDIgY29scz87IGdhaW4gYW5kIHNwZWVkCm11dGF0ZShmbGlnaHRzX3NtbCwKICBnYWluID0gZGVwX2RlbGF5IC0gYXJyX2RlbGF5LAogIHNwZWVkID0gZGlzdGFuY2UgLyBhaXJfdGltZSAqIDYwCikKYGBgCgoKIyMjIyMgNS41LjEgZmlsdGVyIHJvd3Mgd2l0aCBmaWx0ZXIoKQoKIyMjIyMgNS41LjEgZmlsdGVyIHJvd3Mgd2l0aCBmaWx0ZXIoKQoKIyMjIyA1LjUgZmlsdGVyIHJvd3Mgd2l0aCBmaWx0ZXIoKQoKIyMjIyMgNS41LjEgZmlsdGVyIHJvd3Mgd2l0aCBmaWx0ZXIoKQoKIyMjIyMgNS41LjEgZmlsdGVyIHJvd3Mgd2l0aCBmaWx0ZXIoKQoKIyMjIyMgNS41LjEgZmlsdGVyIHJvd3Mgd2l0aCBmaWx0ZXIoKQoKIyMjIyMgNS41LjEgZmlsdGVyIHJvd3Mgd2l0aCBmaWx0ZXIoKQoKIyMjIyMgNS41LjEgZmlsdGVyIHJvd3Mgd2l0aCBmaWx0ZXIoKQoKIyMjIyMgNS41LjEgZmlsdGVyIHJvd3Mgd2l0aCBmaWx0ZXIoKQoKIyMjIyMgNS41LjEgZmlsdGVyIHJvd3Mgd2l0aCBmaWx0ZXIoKQoKIyMjIyA1LjUgZmlsdGVyIHJvd3Mgd2l0aCBmaWx0ZXIoKQoKIyMjIyMgNS41LjEgZmlsdGVyIHJvd3Mgd2l0aCBmaWx0ZXIoKQoKCiMjIFRleHQgTWluaW5nIHdpdGggUgoKIyMjIENoIDI6IFNlbnRpZW50IEFuYWx5c2lzIHdpdGggdGlkeSBEYXRhCgojIyMjIDIuMSBUaGUgc2VudGltZW50cyBkYXRhc2V0CgpgYGB7cn0Kc2VudGltZW50cwpgYGAKCgojIyMgQ2ggMzogQW5hbHl6aW5nIHdvcmQgYW5kIGRvY3VtZW50IGZyZXF1ZW5jeTogdGYtaWRmCgpFeGFtcGxlcyBmcm9tIHRoaXMgY2hhcHRlciB3ZXJlIGFscmVhZHkgZG9uZSBpbiB0aGUgcHJldmlvdXMgaG9tZXdvcmsgYXNzaWdubWVudAo=